CloudWatchのカスタムメトリクスでFreeMemoryMBytes、UsedMemoryPercent、LoadAverage、Stealを取得
CloudWatchで取得できること
CloudWatchはAWSの様々な情報を監視して統計を取ってくれるサービスです。概要については以前ご紹介しました。今回は、標準で提供されていない統計データを登録して取得してみます。いわゆるカスタムメトリクスというやつです。
カスタムメトリクスを取得する方法
今回のカスタムメトリクスで取得する値は以下の4つです。
- 空きメモリー容量(FreeMemoryMBytes):メモリーが少ないからといってメモリ不足とは限らない
- メモリー使用率(UsedMemoryPercent):使用メモリーを合計メモリーで割った割合
- ロードアベレージ(LoadAverage):システムへの平均負荷
- スチール(Steal):CPUリソースを割り当ててもらえなかった時間の割合
続いて、Linuxコマンドを用いて各種値を取得しましょう
freeコマンド
まずは、freeコマンドから
$ free total used free shared buffers cached Mem: 617016 191876 425140 0 11092 145284 -/+ buffers/cache: 35500 581516 Swap: 0 0 0
この標準出力された情報を成型して値を取得します。上記の例ではMemとtotalが交差する値が全メモリー量です。
$ free | grep 'Mem' | tr -s ' ' | cut -d ' ' -f 2 617016
MB(メガバイト)表記にしました。
$ free -m | grep 'Mem' | tr -s ' ' | cut -d ' ' -f 2 602
続いて、メモリー使用率を取得するために空きメモリー量を取得します。
$ free -m | grep 'buffers/cache' | tr -s ' ' | cut -d ' ' -f 4 567
後は計算してあげればメモリー使用率を取得できます。
uptimeコマンド
uptimeコマンドは、本来システムがどの程度連続かどうしているか調べるコマンドですが、ついでにロードアベレージも取得できます。ロードアベレージは、1分前、5分前、15分前までの平均負荷を取る事ができます。今回は1分前を取得します。
$ uptime 12:18:20 up 6:55, 2 users, load average: 0.01, 0.05, 0.05
これを成型します。
$ uptime | tr -s ' ' | cut -d ' ' -f 9 | cut -d ',' -f 1 0.01
取れました!
vmstatコマンド
最後にvmstatです。これは、プロセスの状態、メモリの使用状況など幅広い情報を取得できます。vmstatコマンドの結果からsteal値を取得します。stと書いてある列です。
$ vmstat procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 426544 11136 145280 0 0 2 1 4 8 0 0 99 0 0
これを成型します。
$ vmstat | tail -1 | tr -s ' ' | cut -d ' ' -f 18 0
これで素材は整いました!
CloudWatchのコマンドラインツール
CloudWatchにメトリクスデータを登録するために、CloudWatchコマンドラインツールを使えるようします。
$ wget http://ec2-downloads.s3.amazonaws.com/CloudWatch-2010-08-01.zip $ unzip CloudWatch-2010-08-01.zip $ cd CloudWatch-1.0.12.1 $ cp credential-file-path.template credentials $ vi credentials
CloudWatchを使うには、AWSのアクセスキーが無いといけません。しかし、むやみやたらとAWSのキーをコピーしたくないです。そこで、IAM(Identity and Access Management)でCloudWatchのみの操作を許可したユーザーを作ってあげればOKです。IAMで作成された制限ユーザーのアクセスキーとシークレットキーを保存しました。
AWSAccessKeyId=AKIasfowmeiuxfgoaiwexf(架空) AWSSecretKey=lGZ98yLrnXchZ3847xtoiugxosirughxkrsdsgc(架空)
IAMでCloudWatch専用ユーザーを作成する。
IAMでCloudWatchのカスタムメトリクス登録専用のユーザーを作成します。具体的にはIAMでグループを作成し、ポリシーを付与します。そして、そのグループの下にユーザーを追加します。このユーザーがCloudWatchアクセス専用となるわけです。
ここでは、グループ名をCloudWatchPutDataPolicyとしました。
ポリシーの中身は以下です。
{ "Statement": [ { "Action": [ "cloudwatch:*" ], "Effect": "Allow", "Resource": "*" } ] }
bashで一連の処理を記述する
全ての準備が整いましたので、一連の処理を記述します。
$ cd $ vi custom_metrics_report.sh
中身は以下です。
#!/bin/bash export AWS_CLOUDWATCH_HOME=/home/ec2-user/CloudWatch-1.0.12.1 export AWS_CREDENTIAL_FILE=$AWS_CLOUDWATCH_HOME/credentials export AWS_CLOUDWATCH_URL=https://monitoring.amazonaws.com export PATH=$AWS_CLOUDWATCH_HOME/bin:$PATH export JAVA_HOME=/usr/lib/jvm/jre # get ec2 instance id instanceid=`wget -q -O - http://169.254.169.254/latest/meta-data/instance-id` memtotal=`free -m | grep 'Mem' | tr -s ' ' | cut -d ' ' -f 2` memfree=`free -m | grep 'buffers/cache' | tr -s ' ' | cut -d ' ' -f 4` let "memused=100-memfree*100/memtotal" loadave1=`uptime | tr -s ' ' | cut -d ' ' -f 9 | cut -d ',' -f 1` loadave5=`uptime | tr -s ' ' | cut -d ' ' -f 9 | cut -d ',' -f 2` loadave15=`uptime | tr -s ' ' | cut -d ' ' -f 9 | cut -d ',' -f 3` steal=`vmstat | tail -1 | tr -s ' ' | cut -d ' ' -f 18` mon-put-data --metric-name "FreeMemoryMBytes" --namespace "System/Linux" --dimensions "InstanceId=$instanceid" --value "$memfree" --unit "Megabytes" --region ap-northeast-1 mon-put-data --metric-name "UsedMemoryPercent" --namespace "System/Linux" --dimensions "InstanceId=$instanceid" --value "$memused" --unit "Percent" --region ap-northeast-1 mon-put-data --metric-name "LoadAverage" --namespace "System/Linux" --dimensions "InstanceId=$instanceid" --value "$loadave1" --unit "Count" --region ap-northeast-1 mon-put-data --metric-name "Steal" --namespace "System/Linux" --dimensions "InstanceId=$instanceid" --value "$steal" --unit "Percent" --region ap-northeast-1
いやぁ、、、大作ですw。実行権限を与えます。そして実行してみます。
$ chmod 755 custom_metrics_report.sh $ custom_metrics_report.sh
何もエラーがでなければ成功です。
cronにシェルを登録する
先ほど作ったシェルをcronに登録して自動実行させます。
$ crontab -e
中身はこんな感じ。5分に1回実行する記述です。保存します。
*/5 * * * * /home/ec2-user/custom_metrics_report.sh
登録できているか確認します。
$ crontab -l */5 * * * * /home/ec2-user/custom_metrics_report.sh
大丈夫そうです。5分ほど待ってエラーが無いかログも見てみましょう。
$ sudo cat /var/log/cron Sep 21 12:05:01 ip-10-146-9-61 CROND[21403]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh) Sep 21 12:05:01 ip-10-146-9-61 CROND[21448]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh) Sep 21 12:10:01 ip-10-146-9-61 CROND[21604]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh) Sep 21 12:10:01 ip-10-146-9-61 CROND[21650]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh) Sep 21 12:15:01 ip-10-146-9-61 CROND[21800]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh) Sep 21 12:15:01 ip-10-146-9-61 CROND[21845]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh) Sep 21 12:20:01 ip-10-146-9-61 CROND[21985]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh) Sep 21 12:20:01 ip-10-146-9-61 CROND[22030]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh) Sep 21 12:25:01 ip-10-146-9-61 CROND[22179]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh) Sep 21 12:25:01 ip-10-146-9-61 CROND[22223]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh) Sep 21 12:30:01 ip-10-146-9-61 CROND[22365]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh) Sep 21 12:30:01 ip-10-146-9-61 CROND[22410]: (ec2-user) CMD (/home/ec2-user/custom_metrics_report.sh)
エラーなく実行してくれていました!
Management Consoleで統計データを確認する
最後の確認です。Management Consoleで統計データを確認します。
ステキです。
カスタムメトリクスのアラートを設定する
自動運用に向けてアラートを設定します。5%を5分超えたらアラートです。今回は検証用に低い値を設定しています。
アラートの宛先はトピックです。このトピックはEメールでの通知となっています。
設定した閾値を超えたという表示です。実際に通知が来ているか確認します。
メールが届いていました。
ALARM: "Memory5%Over" in APAC - Tokyo You are receiving this email because your Amazon CloudWatch Alarm "Memory5%Over" in the APAC - Tokyo region has entered the ALARM state, because "Threshold Crossed: 1 datapoint (7.5) was greater than or equal to the threshold (5.0)." at "Wednesday 21 September, 2011 12:52:11 UTC". View this alarm in the AWS Management Console: https://console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#s=Alarms&alarm=Memory5%25Over Alarm Details: - Name: Memory5%Over - Description: - State Change: INSUFFICIENT_DATA -> ALARM - Reason for State Change: Threshold Crossed: 1 datapoint (7.5) was greater than or equal to the threshold (5.0). - Timestamp: Wednesday 21 September, 2011 12:52:11 UTC Threshold: - The alarm is in the ALARM state when the metric is GreaterThanOrEqualToThreshold 5.0 for 300 seconds. Monitored Metric: - MetricNamespace: System/Linux - MetricName: UsedMemoryPercent - Dimensions: [InstanceId = i-98320e99] - Period: 300 seconds - Statistic: Average - Unit: not specified State Change Actions: - OK: - ALARM: [arn:aws:sns:ap-northeast-1:7456745674567456:mytopic1] - INSUFFICIENT_DATA:
まとめ
top/vmstat/uptime/freeなどのおなじみLinuxコマンドの結果を用いて、CloudWatchのカスタムメトリクスを登録できる事が分かりました。このメトリクスにアラートを登録しておけば、通知メールや自動処理を合わせて行う事ができ、EC2インスタンスの運用管理をほとんど任せる事ができるようになるかと思います。CloudWatchのカスタムメトリクスで人力作業をゼロにしましょう!
参考資料
Custom CloudWatch metric for memory? Reporting memory to CloudWatch...